<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Admin\Event;

use Admin\Data\Common;
use Admin\Service\Common\ShopMessage;
use Doctrine\ORM\EntityManager;
use Goods\Entity\GoodsInSpecGoods;
use Goods\Entity\GoodsStock;
use Laminas\EventManager\Event;
use Laminas\EventManager\EventManagerInterface;
use Laminas\EventManager\ListenerAggregateInterface;
use Laminas\I18n\Translator\Translator;
use User\Entity\User;

class EmailListener implements ListenerAggregateInterface
{
    protected $listeners = [];

    private $translator;
    private $entityManager;

    public function __construct(
        EntityManager   $entityManager
    )
    {
        $this->translator       = new Translator();
        $this->entityManager    = $entityManager;
    }

    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $shareEvents = $events->getSharedManager();

        //前台提交订单完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CheckoutController', 'shop.checkout.two.post', [$this, 'onSendAddOrderMail']
        );
        //前台提交订单完成，查看是否缺货，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CheckoutController', 'shop.checkout.two.post', [$this, 'onSendGoodsStockMail']
        );

        //前台订单付款完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\NotifyController', 'shop.order.notifyPayFinish.post', [$this, 'onSendPaymentOrderMail']
        );
        //后台订单付款完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Sales\Controller\IndexController', 'backstage-order.pay.post', [$this, 'onSendPaymentOrderMail']
        );

        //后台订单发货完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Sales\Controller\IndexController', 'backstage-order.ship.post', [$this, 'onSendShipOrderMail']
        );

        //前台订单收货完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\HomeOrderController', 'shop.order.receipt.post', [$this, 'onSendReceiptOrderMail']
        );
        //后台订单收货完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Sales\Controller\IndexController', 'backstage-order.receipt.post', [$this, 'onSendReceiptOrderMail']
        );

        //前台订单取消完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\HomeOrderController', 'shop.order.cancel.post', [$this, 'onSendCancelOrderMail']
        );
        //后台订单取消完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Sales\Controller\IndexController', 'backstage-order.cancel.post', [$this, 'onSendCancelOrderMail']
        );
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            $events->detach($listener);
            unset($this->listeners[$index]);
        }
    }

    /**
     * 前台订单提交发送邮件
     * @param Event $event
     * @return bool
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendAddOrderMail(Event $event)
    {
        $data = $this->checkSendMail($event);
        if(!$data) return false;

        $subject = $this->translator->translate('订单提交提醒');

        $sendArray  = $data['sendArray'];
        $sendArray['addOrderTime'] = $data['orderInfo']->getOrderAddTime();

        return ShopMessage::sendOrderMail($subject, $data['userInfo']->getUserEmail(), $sendArray, 'AddOrder');
    }

    /**
     * 商品缺货提醒
     * @param Event $event
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendGoodsStockMail(Event $event)
    {
        $shopConfig= Common::readConfigFile('config');
        $orderInfo = $event->getParam('orderInfo');
        foreach ($orderInfo->getOrderGoods() as $goodsValue) {
            $goodsStock = $this->entityManager->getRepository(GoodsStock::class)->findOneBy(['goodsId' => $goodsValue->getGoodsId()]);
            if($goodsStock && $goodsStock->getStockShowState() == 0) {
                if($goodsValue->getInSpecGoodsId() > 0) {
                    $inSpecGoodsInfo = $this->entityManager->getRepository(GoodsInSpecGoods::class)->findOneBy(['inSpecGoodsId' => $goodsValue->getInSpecGoodsId(), 'goodsId' => $goodsValue->getGoodsId()]);
                    $stockNum = $inSpecGoodsInfo->getSpecGoodsStock();
                } else {
                    $stockNum = $goodsStock->getStockNum();
                }
                //商品缺货，进行邮件提醒
                if ($goodsStock->getStockOutSetNum() > 0 && $stockNum <= $goodsStock->getStockOutSetNum() && $shopConfig['email']['email_service_state'] == 1) {
                    $sendArray = [];
                    $sendArray['shopName']  = $shopConfig['base']['shop_name'];
                    $sendArray['goodsName']  = $goodsValue->getGoodsName() . ($goodsValue->getInSpecGoodsId() > 0 ? '(' . $goodsValue->getInSpecGoodsStr() . ')' : '');
                    $sendArray['goodsStock'] = $stockNum;
                    ShopMessage::sendOrderMail($this->translator->translate('商品库存缺货提醒'), '', $sendArray, 'GoodsStockOut');
                }
            }
        }
    }

    /**
     * 付款完成，发送邮件
     * @param Event $event
     * @return bool
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendPaymentOrderMail(Event $event)
    {
        $data = $this->checkSendMail($event);
        if(!$data) return false;

        $subject = $this->translator->translate('订单付款提醒');

        $sendArray  = $data['sendArray'];
        $sendArray['paymentOrderTime'] = $data['orderInfo']->getPaymentFinishTime();

        return ShopMessage::sendOrderMail($subject, $data['userInfo']->getUserEmail(), $sendArray, 'PaymentOrder');
    }

    /**
     * 后台发货完成，发送邮件
     * @param Event $event
     * @return bool
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendShipOrderMail(Event $event)
    {
        $data = $this->checkSendMail($event);
        if(!$data) return false;

        $subject = $this->translator->translate('订单发货提醒');

        $sendArray  = $data['sendArray'];
        if($data['orderInfo']->getDeliveryMode() == 2) {//单独配送
            $deliveryName = [];
            $expressNumber= [];
            $orderGoods = $data['orderInfo']->getOrderGoods();
            foreach ($orderGoods as $key => $goodsValue) {
                if($key == 0 && !empty($goodsValue->getExpressTime())) $sendArray['shipOrderTime'] = $goodsValue->getExpressTime();
                if (!empty($goodsValue->getDeliveryName()))     $deliveryName[]    = $goodsValue->getDeliveryName();
                if (!empty($goodsValue->getExpressNumber()))    $expressNumber[]   = $goodsValue->getExpressNumber();
            }
            $sendArray['deliveryName']  = empty($deliveryName)  ? $this->translator->translate('无信息') : implode('|', $deliveryName);
            $sendArray['expressNumber'] = empty($expressNumber) ? $this->translator->translate('无单号') : implode('|', $expressNumber);
        } else {//统一配送
            $sendArray['deliveryName']  = empty($data['orderInfo']->getDeliveryName())  ? $this->translator->translate('无信息') : $data['orderInfo']->getDeliveryName();
            $sendArray['expressNumber'] = empty($data['orderInfo']->getExpressNumber()) ? $this->translator->translate('无单号') : $data['orderInfo']->getExpressNumber();
            $sendArray['shipOrderTime'] = $data['orderInfo']->getExpressTime();
        }

        return ShopMessage::sendOrderMail($subject, $data['userInfo']->getUserEmail(), $sendArray, 'ShipOrder');
    }

    /**
     * 订单收货完成，发送邮件
     * @param Event $event
     * @return bool
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendReceiptOrderMail(Event $event)
    {
        $data = $this->checkSendMail($event);
        if(!$data) return false;

        $subject = $this->translator->translate('订单收货提醒');

        $sendArray  = $data['sendArray'];
        if($data['orderInfo']->getDeliveryMode() == 2) {//单独配送
            $deliveryName = [];
            $expressNumber= [];
            $orderGoods = $data['orderInfo']->getOrderGoods();
            foreach ($orderGoods as $key => $goodsValue) {
                $deliveryName[]    = $goodsValue->getDeliveryName();
                $expressNumber[]   = $goodsValue->getExpressNumber();
            }
            $sendArray['deliveryName']  = empty($deliveryName)  ? $this->translator->translate('无信息') : implode('|', $deliveryName);
            $sendArray['expressNumber'] = empty($expressNumber) ? $this->translator->translate('无单号') : implode('|', $expressNumber);
        } else {//统一配送
            $sendArray['deliveryName']  = empty($data['orderInfo']->getDeliveryName())  ? $this->translator->translate('无信息') : $data['orderInfo']->getDeliveryName();
            $sendArray['expressNumber'] = empty($data['orderInfo']->getExpressNumber()) ? $this->translator->translate('无单号') : $data['orderInfo']->getExpressNumber();
        }
        $sendArray['receiptOrderTime'] = $data['orderInfo']->getOrderFinishTime();

        return ShopMessage::sendOrderMail($subject, $data['userInfo']->getUserEmail(), $sendArray, 'ReceiptOrder');
    }

    /**
     * 订单取消完成，发送邮件
     * @param Event $event
     * @return bool
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendCancelOrderMail(Event $event)
    {
        $data = $this->checkSendMail($event);
        if(!$data) return false;

        $subject = $this->translator->translate('订单取消提醒');

        $sendArray  = $data['sendArray'];
        $sendArray['cancelOrderTime'] = time();

        return ShopMessage::sendOrderMail($subject, $data['userInfo']->getUserEmail(), $sendArray, 'CancelOrder');
    }

    /**
     * 检查mail信息
     * @param $event
     * @return array|bool
     */
    private function checkSendMail($event)
    {
        $orderInfo = $event->getParam('orderInfo');
        $shopConfig= Common::readConfigFile('config');

        if($shopConfig['email']['email_service_state'] != 1) return false;

        $userInfo = $this->entityManager->getRepository(User::class)->findOneBy(['userId' => $orderInfo->getUserId()]);
        if($userInfo == null || empty($userInfo->getUserEmail())) return false;

        $sendArray = [];
        $sendArray['shopName']  = $shopConfig['base']['shop_name'];
        $sendArray['buyName']   = $orderInfo->getUserName();
        $sendArray['orderSn']   = $orderInfo->getOrderSn();
        $sendArray['orderTotal']= $orderInfo->getOrderAmount();
        $sendArray['shopUrl']   = $event->getTarget()->url()->fromRoute('shop', [], ['force_canonical' => true]);

        return ['shopConfig' => $shopConfig, 'orderInfo' => $orderInfo, 'userInfo' => $userInfo, 'sendArray' => $sendArray];
    }
}